package animationEngine;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyVetoException;
import java.io.FileNotFoundException;
import java.util.ArrayList;

import javax.swing.JCheckBoxMenuItem;
import javax.swing.JDesktopPane;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import algorithms.Algorithm;
import algorithms.BoyerMooreTestAlgorithm;
import algorithms.BruteForceTestAlgorithm;
import algorithms.KMPTestAlgorithm;


/**
 * @author ANDREI PALADE
 * 
 * @created 10-Dec-2011, 20:17:42
 * 
 * @version 1.0
 */
public class MainFrame extends javax.swing.JFrame implements ActionListener, ChangeListener{

	/**
	 * @serial using the default one (1L)
	 */
	private static final long serialVersionUID = 1L;
	
	private boolean jobDone = false;
	
	
	private static Dimension screenSize; 
	public boolean alive = true;
	//variable to keep track of the time we have been running so we can update at regular intervals
	//Dave McB
	private float time;
	
	PseudoCodeFrame testPseudo;	//the pseudo code panel
	AnimationControlsFrame controls;	//the buttons for controlling the animation
	StringBoxDisplay testDisplay;
	FullStringBoxDisplay fullBox;
	PreProcessingFrame table;
	InputFrame welcomeFrame;

	
	/** The text that is currently used */
	private String dummyText ;

	/** The pattern that is currently used */
	private String dummyPattern;

	public double currentScale;
	
	boolean playAnimation = false;
	boolean fullBoxOnFocus = true;
	//these variables are used to shift the string after the pattern has passed halfway
	boolean patternMoveExhausted = false;
	int indexPatternMoveExhausted = 0;
	int stringLocationAtExhaustion = 0;
	
	//nice little variable to store running time of our algorithm
	@SuppressWarnings("unused")
	private long executionTime;
	
	//an array list of the possible animation states for this animation (David McBrierty)
	private ArrayList<AnimationState> animationStates = new ArrayList<AnimationState>();
	//the index in this array of the state we are currently displaying (David Mcbrierty)
	private int currentStateIndex = 0;
	
	//the test algorithm we are using to test ou tthe animation states
	Algorithm testAlgorithm;
	
	public Dimension getScreenSize(){
	    return Toolkit.getDefaultToolkit().getScreenSize();
	}
	
	/**This is a method to set up the "MainFrame", ie. the main window that holds other
	 * JInternalFrames that the user interacts with.
	 */
	public MainFrame() {
		screenSize = getScreenSize();
		screenSize.height -= 24;
		
		currentScale = 0.67;
		
		//set time and isRunning so we can update
		this.time = 0;
		
		//initialise the test algorithm (really dumb pointless code at the moment)
		//but it helps us avoid a null pointer
		testAlgorithm = new KMPTestAlgorithm();
	}
	
	public MainFrame(String text, String pattern, String algorithm) {
		screenSize = getScreenSize();
		screenSize.height -= 24;
		this.dummyPattern = pattern;
		this.dummyText = text;
		
		currentScale = 0.67;
		
		//set time and isRunning so we can update
		this.time = 0;
		
		// Selects the algorithm here
		if(algorithm.equalsIgnoreCase("Naive")){
			testAlgorithm = new BruteForceTestAlgorithm();
		}
		else if(algorithm.equalsIgnoreCase("KMP")){
			testAlgorithm = new KMPTestAlgorithm();
		}
		else{
			testAlgorithm = new BoyerMooreTestAlgorithm();
		}
	}
	
	/**
	 * This method is used to run a constant update on our frame, it is called from Main.java.
	 * 
	 * The update is called so that the math can be done to allow us to play, pause and stop the animations.
	 * 
	 * Dave McB
	 * 
	 * @param currentTime The current time in milliseconds
	 */
	public void update(float currentTime){
		this.time += currentTime/1000;
		//System.out.println("Time is now " + this.time);
		if (this.time > (100/controls.speedSlider.getValue()) * 1000){
			if (this.playAnimation){
				if (testAlgorithm instanceof BruteForceTestAlgorithm) {
					displayBruteForceAnimationState(animationStates.get(currentStateIndex));
				}
				else if (testAlgorithm instanceof KMPTestAlgorithm) {
					displayKMPAnimationState(animationStates.get(currentStateIndex));
				}
				else if (testAlgorithm instanceof BoyerMooreTestAlgorithm) {
					displayBoyerMooreAnimationState(animationStates.get(currentStateIndex));
				}
				if(currentStateIndex == animationStates.size()-1){
					//System.out.println("No more states to be displayed");
					this.playAnimation = false;
				}
				else this.currentStateIndex++;
			}
			this.time = 0;
		}
	}
	
	
	@Override
	public void dispose() {
		this.alive = false;
		//System.out.println("We want to exit now.");
	    super.dispose();
	}
	
	/**swapView is a method which takes the 2 JInternalFrame objects "testDisplay" 
	 * and "fullBox" and then swaps them to each of their DEFAULT locations.
	 */
	private void swapView() {
		if (fullBoxOnFocus) {
			testDisplay.setLocation(0, (int) (0.73 * screenSize.height));
		    testDisplay.setSize((int) (currentScale * screenSize.width), (int) (0.27 * screenSize.height));
		    fullBox.setLocation(0, 0); // this should be always 0,0
		    fullBox.setSize((int) (currentScale * screenSize.width), (int) (0.73 * screenSize.height));
		    fullBoxOnFocus = false;
		}
		else {
			fullBox.setLocation(0, (int) (0.73 * screenSize.height));
		    fullBox.setSize((int) (currentScale * screenSize.width), (int) (0.27 * screenSize.height));
		    testDisplay.setLocation(0, 0); // this should be always 0,0
		    testDisplay.setSize((int) (currentScale * screenSize.width), (int) (0.73 * screenSize.height));
		    fullBoxOnFocus = true;
		}
	}
	
	/**Method to set the size and location of the initial 4 JInternalFrame objects.
	 * @throws PropertyVetoException 
	 * 
	 */
	private void initialFrameSetup(double value) {
		//value = 0.67
		//scaleFactor = 0.33
		double scaleFactor = (double)Math.round((1.00-value)*100)/100;
		
		controls.setLocation((int) (value * screenSize.width), 0);
	    controls.setSize((int) (scaleFactor * screenSize.width), (int) (0.19 * screenSize.height));
	    testPseudo.setLocation((int) (value * screenSize.width), (int) (0.19 * screenSize.height));
	    testPseudo.setSize((int) (scaleFactor * screenSize.width), (int) (0.91 * screenSize.height));
	    fullBox.setLocation(0, (int) (0.73 * screenSize.height));
	    fullBox.setSize((int) (value * screenSize.width), (int) (0.27 * screenSize.height));
	    testDisplay.setLocation(0, 0); // this should be always 0,0
	    testDisplay.setSize((int) (value * screenSize.width), (int) (0.73 * screenSize.height));
    	testDisplay.setVisible(true);
    	controls.setVisible(true);
	    testPseudo.setVisible(true);
	    fullBox.setVisible(true);

	}
	
	
	/**Method to set the size and location of the initial 4 JInternalFrame objects.
	 * @throws PropertyVetoException 
	 * 
	 */
	private void initialFrameSetup(double value, boolean hide) {
		//value = 0.67
		//scaleFactor = 0.33
		double scaleFactor = (double)Math.round((1.00-value)*100)/100;
		
		controls.setLocation((int) (value * screenSize.width), 0);
	    controls.setSize((int) (scaleFactor * screenSize.width), (int) (0.19 * screenSize.height));
	    testPseudo.setLocation((int) (value * screenSize.width), (int) (0.19 * screenSize.height));
	    testPseudo.setSize((int) (scaleFactor * screenSize.width), (int) (0.91 * screenSize.height));
	    fullBox.setLocation(0, (int) (0.73 * screenSize.height));
	    fullBox.setSize((int) (value * screenSize.width), (int) (0.27 * screenSize.height));
	    testDisplay.setLocation(0, 0); // this should be always 0,0
	    testDisplay.setSize((int) (value * screenSize.width), (int) (0.73 * screenSize.height));
	    if(hide){
	    	testDisplay.setVisible(false);
	    	controls.setVisible(false);
	    	testPseudo.setVisible(false);
	    	fullBox.setVisible(false);
	    }
	}
	
	
	
	/** This method sets up the View->Switch to ...-> String Box View
	 * 
	 */
	private void stringBoxViewSetup() {
		controls.setLocation((int) (0.67 * screenSize.width), 0);
	    controls.setSize((int) (0.33 * screenSize.width), (int) (0.19 * screenSize.height));
	    testPseudo.setLocation((int) (0.67 * screenSize.width), (int) (0.19 * screenSize.height));
	    testPseudo.setSize((int) (0.33 * screenSize.width), (int) (0.91 * screenSize.height));
	    testDisplay.setLocation(0, 0); // this should be always 0,0
	    testDisplay.setSize((int) (0.67 * screenSize.width), (int) (screenSize.height));
	    if (!testDisplay.isVisible())
	    	testDisplay.setVisible(true);
	    if (!controls.isVisible())
	    	controls.setVisible(true);
	    if (!testPseudo.isVisible())
	    	testPseudo.setVisible(true);
	    fullBox.setVisible(false);
	}
	
	/** This method sets up the View->Switch to ...-> Full Box View
	 *     
	 */
	private void fullBoxViewSetup() {
		controls.setLocation((int) (0.67 * screenSize.width), 0);
	    controls.setSize((int) (0.33 * screenSize.width), (int) (0.19 * screenSize.height));
	    testPseudo.setLocation((int) (0.67 * screenSize.width), (int) (0.19 * screenSize.height));
	    testPseudo.setSize((int) (0.33 * screenSize.width), (int) (0.91 * screenSize.height));
	    fullBox.setLocation(0, 0); // this should be always 0,0
	    fullBox.setSize((int) (0.67 * screenSize.width), (int) (screenSize.height));
	    if (!fullBox.isVisible())
	    	fullBox.setVisible(true);
	    if (!controls.isVisible())
	    	controls.setVisible(true);
	    if (!testPseudo.isVisible())
	    	testPseudo.setVisible(true);
	    testDisplay.setVisible(false);
	}
	/*
	private void displayStartDialogBox() {
		
		// When we launch the input frame we make the parent invisible
		// if the user wants to cancel a new input we keep the parent 
		// and make it visible again in the same stage
		this.setVisible(false);
		welcomeFrame = new InputFrame();
		welcomeFrame.setTextSize(40);
		welcomeFrame.setPatternSize(20);
		welcomeFrame.setPreviousPattern(dummyPattern);
		welcomeFrame.setPreviousText(dummyText);
		welcomeFrame.setParentFrame(this);
		welcomeFrame.setVisible(true);
		welcomeFrame.setLocationRelativeTo(null);
		welcomeFrame.pack();
	}*/
	
	// display border table or last occurrence in pattern talbe (for KMP or Boyer-Moore respectively)
	@SuppressWarnings("unused")
	private void displayTable() { 
		StringBox indexBox = null;
		JPanel indexBoxPanel = null;
		StringBox tableBox = null;
		JPanel tableBoxPanel = null;
		JLabel tableLabel = null;
		JPanel tableLabelPanel = null;
		
		JPanel listPane = new JPanel();
		//listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));
		
		String tableString = "";
		String indexString = "";
		
		int [] t;
		
		// set for each algorithm separately
		if (testAlgorithm instanceof KMPTestAlgorithm) {			
			table = new PreProcessingFrame(screenSize, this.testDisplay.getPattern(), PreProcessingFrame.BORDER_TABLE);
		}
		else if (testAlgorithm instanceof BoyerMooreTestAlgorithm) {			
			
		}
		else {
			table.setVisible(false);
		}	
	}
		
	/**Very large method to initialise the menu bar, add JMenus, add JMenuItems and
	 * and also add action listeners etc.
	 */
	public JMenuBar createMenuBar(){
		
	    //Sets up Menu Bar
	    JMenuBar menuBar = new JMenuBar();
	    
	    //setJMenuBar(menuBar);
	    
	    //Sets up a menu and adds it to the menu bar 
	    JMenu fileMenu = new JMenu("Start");
	    menuBar.add(fileMenu);
	    
	    //Creates a menu item for the exit function
	    JMenuItem exitMI = new JMenuItem("Exit");
	    exitMI.addActionListener(new ActionListener() {
	    	
	    	@Override
	    	public void actionPerformed(ActionEvent e) {
	    		
	    		setJobDone(true);
	    		System.exit(0);
	    	}
	    });
	    
	    //Creates a menu item for the open the welcome frame 	    
	    JMenuItem openWelcomeFrameMI = new JMenuItem("New");
	    openWelcomeFrameMI.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {

				
				// Display the input frame now 
				//displayStartDialogBox();
				setVisible(false);
				setJobDone(true);
			}
		});
	    
	    
	    //Adds the menu items to the fileMenu
	    fileMenu.add(openWelcomeFrameMI);	    
	    fileMenu.add(exitMI);
	    
	    
	    
	    // Create the view menu and add it to the menuBar
	    JMenu viewMenu = new JMenu("View");
	    
	    final JCheckBoxMenuItem fullView = new JCheckBoxMenuItem("Full");
	    final JCheckBoxMenuItem sectionView = new JCheckBoxMenuItem("Section");
	    final JCheckBoxMenuItem pseudoView = new JCheckBoxMenuItem("Pseudocode");
	    final JCheckBoxMenuItem controlsView = new JCheckBoxMenuItem("Controls");   
	    JSeparator separator = new JSeparator();
	    JMenu configureSubMenu = new JMenu("Configure");
	    final JMenuItem swapViews = new JMenuItem("Swap Views");
	    JMenuItem resetView = new JMenuItem("Reset"); 
	    JMenu switchToSubMenu = new JMenu("Switch to");
	    JMenuItem stringBoxView = new JMenuItem("String-Box View");
	    JMenuItem fullBoxView = new JMenuItem("Full-Box View");
	    JMenu helpMenu = new JMenu("About");
	    JMenuItem aboutTeamMI = new JMenuItem("Team");
	    JMenuItem aboutProjectMI = new JMenuItem("Project");
	    
	    fullView.setState(true);
	    pseudoView.setState(true);
	    sectionView.setState(true);
	    controlsView.setState(true);
	    	    
	    menuBar.add(viewMenu);
	   
	    pseudoView.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				if(pseudoView.getState() == true) {
					testPseudo.setVisible(true);
					if (controlsView.getState() == true) {
					    testPseudo.setLocation((int) (currentScale * screenSize.width), (int) (0.19 * screenSize.height));
					    testPseudo.setSize((int) ((1.00 - currentScale) * screenSize.width), (int) (0.91 * screenSize.height));
						controls.setLocation((int) (currentScale * screenSize.width), 0);
					    controls.setSize((int) ((1.00 - currentScale) * screenSize.width), (int) (0.19 * screenSize.height));
					}
					else {
						testPseudo.setLocation((int) (currentScale * screenSize.width), 0);
					    testPseudo.setSize((int) ((1.00 - currentScale) * screenSize.width), screenSize.height);
					}
				}
				
				else {
					testPseudo.setVisible(false);
					if (controlsView.getState() == true) {
						controls.setLocation((int) (currentScale * screenSize.width), 0);
					    controls.setSize((int) ((1.00 - currentScale) * screenSize.width), screenSize.height);
					}
				}
			}
		});
	    viewMenu.add(pseudoView);
	    	    
	    // Create the section view menu button
	    sectionView.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				if(sectionView.getState() == true)
					testDisplay.setVisible(true);
				else
					testDisplay.setVisible(false);
			}
		});
	    viewMenu.add(sectionView);
	    
	    fullView.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				if(fullView.getState() == true)
					fullBox.setVisible(true);
				else 
					fullBox.setVisible(false);	
			}
		});
	    viewMenu.add(fullView);
	        
	    controlsView.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				if(controlsView.getState() == true) {
					controls.setVisible(true);
					if (pseudoView.getState() == true) {
						controls.setLocation((int) (currentScale * screenSize.width), 0);
					    controls.setSize((int) ((1.00 - currentScale) * screenSize.width), (int) (0.19 * screenSize.height));
						testPseudo.setLocation((int) (currentScale * screenSize.width), (int) (0.19 * screenSize.height));
					    testPseudo.setSize((int) ((1.00 - currentScale) * screenSize.width), (int) (0.91 * screenSize.height));
					}
					else {
						controls.setLocation((int) (currentScale * screenSize.width), 0);
						controls.setSize((int) ((1.00 - currentScale) * screenSize.width), screenSize.height);
					}
				}
				else {
					controls.setVisible(false);
					if (pseudoView.getState() == true) {
						testPseudo.setLocation((int) (currentScale * screenSize.width), 0);
						testPseudo.setSize((int) ((1.00 - currentScale) * screenSize.width), screenSize.height);
					}
				}
			}
		});
	    viewMenu.add(controlsView);
	    viewMenu.add(separator);
	    viewMenu.add(configureSubMenu);
	    
	    swapViews.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				swapView();
			}
		});
	    configureSubMenu.add(swapViews);
	    
	    resetView.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				
				// When reset, use the current scale factor 
				initialFrameSetup(currentScale);
				displayTable();
				fullView.setState(true);
				sectionView.setState(true);
				controlsView.setState(true);
				pseudoView.setState(true);
			}
		});
	    configureSubMenu.add(resetView);
	    
	   
	    
	    viewMenu.add(switchToSubMenu);
	    
	    stringBoxView.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				stringBoxViewSetup();
				fullView.setState(false);
				sectionView.setState(true);
				controlsView.setState(true);
				pseudoView.setState(true);
			}
		});
	    switchToSubMenu.add(stringBoxView);
	    
	    fullBoxView.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				fullBoxViewSetup();
				sectionView.setState(false);
				fullView.setState(true);
				controlsView.setState(true);
				pseudoView.setState(true);
			}
		});
	    switchToSubMenu.add(fullBoxView);
	          
	    
	    
	    menuBar.add(helpMenu);
	        
	    aboutTeamMI.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// Create a new aboutTeam object
				Team aboutTeam = new Team();
				aboutTeam.initComponents();
				aboutTeam.setVisible(true);
				aboutTeam.setLocationRelativeTo(null);
				aboutTeam.pack();
			}
		});
	    
	    //Adds the menu items to the helpMenu
	    helpMenu.add(aboutTeamMI);
	    
	    aboutProjectMI.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// Create a new aboutFrame object
				Project aboutProject = new Project();
				aboutProject.initComponents();
				aboutProject.setVisible(true);
				aboutProject.setLocationRelativeTo(null);
				aboutProject.pack();
				
			}
		});
	    
	    helpMenu.add(aboutProjectMI);
	    
	    return menuBar;
	}
	
	public void init() throws FileNotFoundException, InterruptedException {
	    //Make the frame full screen
	    setResizable(false);
	    setSize(screenSize);
	    setUndecorated(true);	    
	       
	    JDesktopPane dtp = new JDesktopPane();
	    this.setJMenuBar(this.createMenuBar());
	    setContentPane(dtp);
	    testDisplay = new StringBoxDisplay(dummyText,dummyPattern);
	    dtp.add(testDisplay);
	  
	    
	    fullBox = new FullStringBoxDisplay(dummyText,dummyPattern);
	    final int oldSize = fullBox.getWidth();
	    //fullBox.setContentPane(list);
	    fullBox.addComponentListener(new ComponentListener() {
			
			@Override
			public void componentShown(ComponentEvent arg0) {}
			
			@Override
			public void componentResized(ComponentEvent arg0) {
				//Font STRING_DISPLAY_FONT = new Font("Courier", Font.PLAIN, 24);
				float fontSize = fullBox.textBox.getFont().getSize2D();
				int newSize = fullBox.getWidth();
				int fontSize2 = (int)((float)newSize * fontSize / (float)oldSize);
				//fullBox.removeAll();
				fullBox.textBox.setFontSize(fontSize2);
				fullBox.patternBox.setFontSize(fontSize2);
				
			}
			
			@Override
			public void componentMoved(ComponentEvent arg0) {}
			
			@Override
			public void componentHidden(ComponentEvent arg0) {}
		});
	    
	    dtp.add(fullBox);
	    
	    if (testAlgorithm instanceof BruteForceTestAlgorithm) {
			testPseudo = new PseudoCodeFrame("BF");
		}
		else if (testAlgorithm instanceof KMPTestAlgorithm) {
			testPseudo = new PseudoCodeFrame("KMP");
		}
		else if (testAlgorithm instanceof BoyerMooreTestAlgorithm) {
			testPseudo = new PseudoCodeFrame("BM");
		}
	    dtp.add(testPseudo);
	    
	    controls = new AnimationControlsFrame(this);
	    dtp.add(controls);
	    
	    if (testAlgorithm instanceof KMPTestAlgorithm) {
	    	table = new PreProcessingFrame(screenSize, dummyPattern, PreProcessingFrame.BORDER_TABLE);
	    	 dtp.add(table, new Integer(10));
		}
		else if (testAlgorithm instanceof BoyerMooreTestAlgorithm) {
			table = new PreProcessingFrame(screenSize, dummyPattern, PreProcessingFrame.LAST_OCCURRENCE_TABLE);
			 dtp.add(table, new Integer(10));
		}
	   
	    // This is the initial setup
	    initialFrameSetup(0.67);
	    //displayTable();
	    dtp.setOpaque(false);
	    setVisible(true);
	    addWindowListener(new WindowAdapter() {
	      public void windowClosing(WindowEvent e) {
	        setVisible(false);
	        dispose();
	        System.exit(0);
	      }
	    });
	    
		
		//load in the animation states from the brute force algorithm
		//the test algorithm currently prints stuff to standard out when it is generating
		//the states which slows the load time of the program down, the final version
		//wont do this as we wont print the stuff out to output
	    long start = System.currentTimeMillis();
		animationStates = testAlgorithm.getStates(this.testDisplay.textBox.stringUsed, this.testDisplay.patternBox.stringUsed);
		long end = System.currentTimeMillis();
		this.executionTime = end - start;
		//System.out.println("ALGORITHM START " + start);
		//System.out.println("ALGORITHM END " + start);
		//System.out.println("ALGORITHM TOOK " + this.executionTime + "MS TO EXECUTE");
		/*for (AnimationState state : animationStates)
		{
			System.out.println(animationStates.indexOf(state) + ":" + state);
		}*/
		
		if (testAlgorithm instanceof BruteForceTestAlgorithm) {
			displayBruteForceAnimationState(animationStates.get(currentStateIndex));
		}
		else if (testAlgorithm instanceof KMPTestAlgorithm) {
			displayKMPAnimationState(animationStates.get(currentStateIndex));
		}
		else if (testAlgorithm instanceof BoyerMooreTestAlgorithm) {
			displayBoyerMooreAnimationState(animationStates.get(currentStateIndex));
		}
		
		
	}
	
	/**
	 * This method is used to display the animation state associated with the 
	 * currentStateIndex.
	 */
	public void displayBruteForceAnimationState(AnimationState state){
		//System.out.println("DISPLAY STATE " + this.currentStateIndex + "=" + state);
		this.testPseudo.clearCurrentLineHighlight();		
		this.testPseudo.highlightLine(state.lineOfPseudoCode);
		
		
		
		//something to happen when we cannot find what we a re looking for and text has been exhausted
		//ie the last pseudo code line
		if(state.lineOfPseudoCode == 11){

			//by default the pattern position should be the index the string was found
			String message = "<html> EXECUTION COMPLETED <br>" +
			"String Length: "  + this.testDisplay.textBox.getStringUsed().length()+"<br />"+
			"Pattern Length: "  + this.testDisplay.patternBox.getStringUsed().length()+"<br />"+
			"Index Of Pattern In String: "  + state.positionOfPattern + "<br />"+
			//"Number Of Comparisons: "  + this.testDisplay.textBox.getStringUsed().length()+"<br />"+
			"</html>";
			JOptionPane.showMessageDialog(this, message);
			return;
		}
		if(state.lineOfPseudoCode == 14){
			//System.out.println("We have reached the end of the algorithm without finiding what we need");
			this.testDisplay.textBox.setBackgroundColor(Color.RED);
			this.fullBox.textBox.setBackgroundColor(Color.RED);
			String message = "<html> EXECUTION COMPLETED <br>" +
					"Pattern has NOT been found. <br />";
			JOptionPane.showMessageDialog(this, message);
			return;
		}
		
		
		
		//if string is too big to fit in the display
		if (this.testDisplay.textBox.getWidth() > this.testDisplay.getWidth()){

			//if pattern is past half way in string box
			if (((44*state.positionOfPattern)+(this.testDisplay.patternBox.getWidth()/2)) > (this.testDisplay.getWidth()/2)){

				//SHIFT THE STRING INSTEAD
				if (!patternMoveExhausted){
					//first time we reach here set the pattern move exhausted index
					this.indexPatternMoveExhausted = state.startingIndexInText;
					this.stringLocationAtExhaustion = this.testDisplay.textBoxPanel.getLocation().x;
					this.patternMoveExhausted = true;

				}
				//we only want the string to shift if we havent found a character match
				if (!state.matches){
					this.testDisplay.textBoxPanel.setLocation(this.stringLocationAtExhaustion-(44*(state.startingIndexInText - this.indexPatternMoveExhausted)), 
							this.testDisplay.textBoxPanel.getLocation().y);
				}
			}
			else {
				//just move pattern
				this.testDisplay.movePatternTo(44*state.positionOfPattern);
			}
		}
		else {
			//just move pattern
			this.testDisplay.movePatternTo(44*state.positionOfPattern);
		}
		int shiftdistance = (int) (fullBox.textBox.getSize().getWidth()/fullBox.textBox.getStringUsed().length());
		this.fullBox.movePatternTo((shiftdistance*state.positionOfPattern));
		

		// We scale the windows for the boxes to fit the screen
		if(this.currentStateIndex == 0){
			double edge = (fullBox.getSize().width - fullBox.textBox.getSize().getWidth())/2;
			double scale = 0.50;

			while (edge > 8 || edge < 0){
				if(scale > 0.68){
					break;
				}
				scale = scale + 0.01;
				initialFrameSetup(scale, true);
				edge = (fullBox.getSize().width - fullBox.textBox.getSize().getWidth())/2;
			}


			this.currentScale = scale;
			this.controls.setVisible(true);
			this.testPseudo.setVisible(true);
			this.fullBox.setVisible(true);
			this.testDisplay.setVisible(true);
		}
		if(state.highlightedPatternCharacter != dummyPattern.length()){
			this.testDisplay.patternBox.highlightChar(state.highlightedPatternCharacter,state.matches);
			this.fullBox.patternBox.highlightChar(state.highlightedPatternCharacter,state.matches);
		}

		if (state.highlightedPatternCharacter == dummyPattern.length()){
			this.testDisplay.patternBox.highlightMatchedChar(0, dummyPattern.length()-1);
			this.fullBox.patternBox.highlightMatchedChar(0, dummyPattern.length());
			return;
		}
		
		this.testDisplay.textBox.highlightChar(state.highlightedTextCharacter,state.matches);
		this.fullBox.textBox.highlightChar(state.highlightedTextCharacter,state.matches);

		if(state.matches && state.lineOfPseudoCode == 1){

			//highlight the chars in the string box pattern and string
			this.testDisplay.patternBox.highlightMatchedChar(state.highlightedPatternCharacter);
			this.testDisplay.textBox.highlightMatchedCharBF(state.startingIndexInText-state.highlightedPatternCharacter,state.highlightedTextCharacter);

			//highlight the chars in the full string box pattern and string
			this.fullBox.patternBox.highlightMatchedChar(state.highlightedPatternCharacter);
			this.fullBox.textBox.highlightMatchedCharBF(state.startingIndexInText-state.highlightedPatternCharacter,state.highlightedTextCharacter);
		}
		if(state.matches && state.lineOfPseudoCode == 2){

			//highlight the chars in the string box pattern and string
			this.testDisplay.patternBox.highlightMatchedChar(state.highlightedPatternCharacter);

			//highlight the chars in the full string box pattern and string
			this.fullBox.patternBox.highlightMatchedChar(state.highlightedPatternCharacter);
		}
		
		
		if(!state.matches && state.lineOfPseudoCode == 5){
			this.testDisplay.patternBox.highlightUnmatchedChar(state.highlightedPatternCharacter);
			this.testDisplay.textBox.highlightUnmatchedChar(state.highlightedTextCharacter);
			
			this.fullBox.patternBox.highlightUnmatchedChar(state.highlightedPatternCharacter);
			this.fullBox.textBox.highlightUnmatchedChar(state.highlightedTextCharacter);
		}
		
		//set all previous characters to red
		//only go up to start of pattern position
		for (int i = 0; i < state.positionOfPattern; i++){
			if (!state.matches){
				this.testDisplay.textBox.highlightChar(i, Color.RED);
				this.fullBox.textBox.highlightChar(i, Color.RED);
			}
		}	
	}
	
	/**
	 * This method is used to display the animation state associated with the 
	 * currentStateIndex.
	 */
	public void displayKMPAnimationState(AnimationState state){
		//System.out.println("DISPLAY STATE " + this.currentStateIndex + "=" + state);
		
		this.testPseudo.clearCurrentLineHighlight();		
		this.testPseudo.highlightLine(state.lineOfPseudoCode);
		
		//something to happen when we cannot find what we a re looking for and text has been exhausted
		//ie the last pseudo code line
		if(state.lineOfPseudoCode == 7){

			//by default the pattern position should be the index the string was found
			String message = "<html> EXECUTION COMPLETED <br />" +
			"String Length: "  + this.testDisplay.textBox.getStringUsed().length()+"<br />"+
			"Pattern Length: "  + this.testDisplay.patternBox.getStringUsed().length()+"<br />"+
			"Index Of Pattern In String :"  + state.positionOfPattern + "<br>"+
			"Number Of Comparisons :"  + this.testDisplay.textBox.getStringUsed().length()+"<br />"+
			"</html>";
			JOptionPane.showMessageDialog(this, message);
			//"We have reached the end of the algorithm SUCCESS:" + state.positionOfPattern
			return;
		}
		if(state.lineOfPseudoCode == 19){
			//System.out.println("We have reached the end of the algorithm without finiding what we need");
			this.testDisplay.textBox.setBackgroundColor(Color.RED);
			this.fullBox.textBox.setBackgroundColor(Color.RED);
			JOptionPane.showMessageDialog(this, "We have reached the end of the algorithm FAILURE");
			return;
		}
		
		
		
		//if string is too big to fit in the display
		if (this.testDisplay.textBox.getWidth() > this.testDisplay.getWidth()){

			//if pattern is past half way in string box
			if (((44*state.positionOfPattern)+(this.testDisplay.patternBox.getWidth()/2)) > (this.testDisplay.getWidth()/2)){
				//System.out.println("PATTERN HAS PAST HALF WAY");
				//SHIFT THE STRING INSTEAD
				if (!patternMoveExhausted){
					//first time we reach here set the pattern move exhausted index
					this.indexPatternMoveExhausted = state.startingIndexInText;
					this.stringLocationAtExhaustion = this.testDisplay.textBoxPanel.getLocation().x;
					this.patternMoveExhausted = true;
					
				}
				//we only want the string to shift if we havent found a character match
				if (!state.matches){
				this.testDisplay.textBoxPanel.setLocation(this.stringLocationAtExhaustion-(44*(state.startingIndexInText - this.indexPatternMoveExhausted)), 
						this.testDisplay.textBoxPanel.getLocation().y);
				}
			}
			else {
				//just move pattern
				this.testDisplay.movePatternTo(44*state.positionOfPattern);
			}
		}
		else {
			//just move pattern
			this.testDisplay.movePatternTo(44*state.positionOfPattern);
		}

		int shiftdistance = (int) (fullBox.textBox.getSize().getWidth()/fullBox.textBox.getStringUsed().length());
		this.fullBox.movePatternTo(/*fullBox.patternBox.getLocation().x+*/(shiftdistance*state.positionOfPattern));


		// THIS SCALING FACTOR 
		if(this.currentStateIndex == 0){
			double edge = (fullBox.getSize().width - fullBox.textBox.getSize().getWidth())/2;
			double scale = 0.50;
			while (edge > 8 || edge < 0){
				if(scale > 0.68){
					break;
				}
				scale = scale + 0.01;
				initialFrameSetup(scale, true);
				edge = (fullBox.getSize().width - fullBox.textBox.getSize().getWidth())/2;
			}


			this.currentScale = scale;
			this.controls.setVisible(true);
			this.testPseudo.setVisible(true);
			this.fullBox.setVisible(true);
			this.testDisplay.setVisible(true);
		}


		//if we are not at the end of the pattern then we are just dealing with a normal highlight
		if(state.highlightedPatternCharacter != dummyPattern.length()){
			this.testDisplay.patternBox.highlightChar(state.highlightedPatternCharacter,state.matches);
			//System.out.println("Highlighting border table char=" + state.highlightedPatternCharacter);
			this.table.indexBox.highlightChar(state.highlightedPatternCharacter,state.matches);
			this.table.tableBox.highlightChar(state.highlightedPatternCharacter,state.matches);
			//table.revalidate();
			this.fullBox.patternBox.highlightChar(state.highlightedPatternCharacter,state.matches);
		}
		//if we are dealing with the end character of the pattern
		if (state.highlightedPatternCharacter == dummyPattern.length()){
			this.testDisplay.patternBox.highlightMatchedChar(0, dummyPattern.length()-1);
			this.fullBox.patternBox.highlightMatchedChar(0, dummyPattern.length()-1);
			return;
		}
		
		
		//highlight the characters that we are on in the text box
		this.testDisplay.textBox.highlightChar(state.highlightedTextCharacter,state.matches);
		this.fullBox.textBox.highlightChar(state.highlightedTextCharacter,state.matches);
		
		
		if(!state.matches && (state.lineOfPseudoCode == 14 || state.lineOfPseudoCode == 15)){
			this.testDisplay.textBox.highlightChar(state.highlightedTextCharacter-1, Color.RED);
			this.fullBox.textBox.highlightChar(state.highlightedTextCharacter-1, Color.RED);
		}
		//if we have a match and we are on pseudo code line two (ie a new match)
		if(state.matches && (state.lineOfPseudoCode == 2)){			
			//highlight the chars in the string box pattern and string
			this.testDisplay.patternBox.highlightMatchedChar(state.highlightedPatternCharacter);
			this.testDisplay.textBox.highlightMatchedCharBF(state.startingIndexInText-state.highlightedPatternCharacter,state.highlightedTextCharacter);
			//highlight the chars in the full string box pattern and string
			this.fullBox.patternBox.highlightMatchedChar(state.highlightedPatternCharacter);
			this.fullBox.textBox.highlightMatchedCharBF(state.startingIndexInText-state.highlightedPatternCharacter,state.highlightedTextCharacter);
		}
		if(state.matches && (state.lineOfPseudoCode == 3)){			
			//highlight the chars in the string box pattern and string
			this.testDisplay.patternBox.highlightMatchedChar(state.highlightedPatternCharacter);
			this.testDisplay.textBox.highlightMatchedCharBF(state.startingIndexInText-state.highlightedPatternCharacter,state.highlightedTextCharacter-1);
			//highlight the chars in the full string box pattern and string
			this.fullBox.patternBox.highlightMatchedChar(state.highlightedPatternCharacter);
			this.fullBox.textBox.highlightMatchedCharBF(state.startingIndexInText-state.highlightedPatternCharacter,state.highlightedTextCharacter-1);
		}
		//if we currently dont match and we are on pseudo code line 9 (ie a new mis match)
		if(!state.matches && state.lineOfPseudoCode == 9){
			//set the string box chars backgrounds to red
			this.testDisplay.patternBox.highlightUnmatchedChar(state.highlightedPatternCharacter);
			this.testDisplay.textBox.highlightUnmatchedChar(state.highlightedTextCharacter);
			//set the full string box chars backgrounds to red
			this.fullBox.patternBox.highlightUnmatchedChar(state.highlightedPatternCharacter);
			this.fullBox.textBox.highlightUnmatchedChar(state.highlightedTextCharacter);
		}
		
		//highlight the border table
		if(!state.matches && state.lineOfPseudoCode == 10){
			//System.out.println("Highlighted pattern char=" + state.highlightedPatternCharacter);
			//System.out.println("Highlighted text char=" + state.highlightedTextCharacter);
			@SuppressWarnings("unused")
			int index = state.highlightedPatternCharacter+(state.highlightedTextCharacter-state.highlightedPatternCharacter);
			//System.out.println("Trying to highlight border table index=" + index);
			this.table.tableBox.highlightChar(state.highlightedPatternCharacter,Color.BLUE);
			
			int borderTableNumber = Integer.parseInt(""+this.table.tableBox.getStringUsed().charAt(state.highlightedPatternCharacter));
			int startIndex = state.highlightedTextCharacter-borderTableNumber;
			for (int i = startIndex; i < state.highlightedTextCharacter; i++){
				this.testDisplay.textBox.highlightChar(i, Color.BLUE);
			}
		}
		
		
		//set all previous characters to red
		//only go up to start of pattern position
		for (int i = 0; i < state.positionOfPattern; i++){
			if (!state.matches){
				this.testDisplay.textBox.highlightChar(i, Color.RED);
				this.fullBox.textBox.highlightChar(i, Color.RED);
			}
		}
		
		//clear all characters in front of currently selected index of border table to white
		for (int i = state.highlightedPatternCharacter+1; 
		i < this.table.tableBox.getStringUsed().length();
		i++){
			this.table.tableBox.highlightChar(i, Color.WHITE);
			this.table.indexBox.highlightChar(i, Color.WHITE);
		}
	}
	
	/**
	 * This method is used to display the animation state associated with the 
	 * currentStateIndex.
	 */
	public void displayBoyerMooreAnimationState(AnimationState state){
		//System.out.println("DISPLAY STATE " + this.currentStateIndex + "=" + state);
		//set the highlighted line of pseudo code
		this.testPseudo.clearCurrentLineHighlight();
		
		this.testPseudo.highlightLine(state.lineOfPseudoCode);
		//shift the pattern box to the right location
		//cell width is currently 44 pixels
		
		//something to happen when we cannot find what we a re looking for and text has been exhausted
		//ie the last pseudo code line
		if(state.lineOfPseudoCode == 22){

			//by default the pattern position should be the index the string was found
			String message = "<html> EXECUTION COMPLETED <br />" +
			"String Length: "  + this.testDisplay.textBox.getStringUsed().length()+"<br />"+
			"Pattern Length: "  + this.testDisplay.patternBox.getStringUsed().length()+"<br />"+
			"Index Of Pattern In String: "  + state.positionOfPattern + "<br />"+
			"Number Of Comparisons: "  + this.testDisplay.textBox.getStringUsed().length()+"<br />"+
			"</html>";
			JOptionPane.showMessageDialog(this, message);
			//"We have reached the end of the algorithm SUCCESS:" + state.positionOfPattern
			//);
			return;
		}
		if(state.lineOfPseudoCode == 24) {
			//System.out.println("We have reached the end of the algorithm without finding what we need");
			this.testDisplay.textBox.setBackgroundColor(Color.RED);
			this.fullBox.textBox.setBackgroundColor(Color.RED);
			JOptionPane.showMessageDialog(this, "We have reached the end of the algorithm.\nNO match was found!");
			return;
		}
				
		int shiftdistance = (int)fullBox.textBox.getSize().getWidth()/fullBox.textBox.getStringUsed().length();

		//if string is too big to fit in the display
		if (this.testDisplay.textBox.getWidth() > this.testDisplay.getWidth()){
			//System.out.println("STRING IS TOO BIG FOR DISPLAY");
			//if pattern is past half way in string box
			if (((44*state.positionOfPattern)+(this.testDisplay.patternBox.getWidth()/2)) > (this.testDisplay.getWidth()/2)){
				//System.out.println("PATTERN HAS PAST HALF WAY");
				//SHIFT THE STRING INSTEAD
				if (!patternMoveExhausted){
					//first time we reach here set the pattern move exhausted index
					this.indexPatternMoveExhausted = state.startingIndexInText;
					this.stringLocationAtExhaustion = this.testDisplay.textBoxPanel.getLocation().x;
					this.patternMoveExhausted = true;
				}
				//we only want the string to shift if we havent found a character match
				if (!state.matches){
					this.testDisplay.textBoxPanel.setLocation(this.stringLocationAtExhaustion-(44*(state.startingIndexInText - this.indexPatternMoveExhausted)), 
							this.testDisplay.textBoxPanel.getLocation().y);
				}
			}
			else {
				//just move pattern
				this.testDisplay.movePatternTo(44*state.positionOfPattern);
			}
		}
		else {
			//just move pattern
			this.testDisplay.movePatternTo(44*state.positionOfPattern);
		}
		//this.testDisplay.movePatternTo(44*state.positionOfPattern);

		this.fullBox.movePatternTo(/*fullBox.patternBox.getLocation().x+*/(shiftdistance*state.positionOfPattern));

		if(this.currentStateIndex == 0){
			// We scale the windows for the boxes to fit the screen
			double edge = (fullBox.getSize().width - fullBox.textBox.getSize().getWidth())/2;
			double scale = 0.50;
			while (edge > 8 || edge < 0){
				if(scale > 0.68){
					break;
				}
				scale = scale + 0.01;
				initialFrameSetup(scale, true);
				edge = (fullBox.getSize().width - fullBox.textBox.getSize().getWidth())/2;
			}

			this.currentScale = scale;
			this.controls.setVisible(true);
			this.testPseudo.setVisible(true);
			this.fullBox.setVisible(true);
			this.testDisplay.setVisible(true);
		}
		
		//if we are not at the end of the pattern then we are just dealing with a normal highlight
		if(state.highlightedPatternCharacter != dummyPattern.length() && state.highlightedPatternCharacter >= 0) {
			this.testDisplay.patternBox.highlightChar(state.highlightedPatternCharacter,state.matches);
			//System.out.println("Highlighting border table char=" + state.highlightedPatternCharacter);
			this.table.indexBox.highlightChar(state.highlightedPatternCharacter,state.matches);
			this.table.tableBox.highlightChar(state.highlightedPatternCharacter,state.matches);
			this.testDisplay.patternBox.highlightChar(state.highlightedPatternCharacter,state.matches);
			this.fullBox.patternBox.highlightChar(state.highlightedPatternCharacter,state.matches);
		}
		//if we are dealing with the end character of the pattern
		if (state.highlightedPatternCharacter == dummyPattern.length()) {
			this.testDisplay.patternBox.highlightMatchedChar(0, dummyPattern.length()-1);
			this.fullBox.patternBox.highlightMatchedChar(0, dummyPattern.length()-1);
			return;
		}
				
		this.testDisplay.patternBox.highlightChar(state.highlightedPatternCharacter);
		this.testDisplay.textBox.highlightChar(state.highlightedTextCharacter);

		/* Hristo: there is a bug here, which I think is caused by the FullBox (outside the scope of this function)
		 		   also, the green highlighting in the StringBox display does not work the same way as in the Full Box, although the code is identical for both 
		 		   use either line (1) or (2) below for testing */
		//if (!state.matches && (state.lineOfPseudoCode == 7 && state.lineOfPseudoCode == 8)) { // (1)
		if (!state.matches && (state.lineOfPseudoCode >= 8 && state.lineOfPseudoCode <= 16) && (state.lineOfPseudoCode != 10 && state.lineOfPseudoCode != 14)) { // (2)
			//set the string box chars backgrounds to red
			this.testDisplay.patternBox.highlightUnmatchedChar(state.highlightedPatternCharacter);
			this.testDisplay.textBox.highlightUnmatchedChar(state.highlightedTextCharacter);
			//set the full string box chars backgrounds to red
			this.fullBox.patternBox.highlightUnmatchedChar(state.highlightedPatternCharacter);
			this.fullBox.textBox.highlightUnmatchedChar(state.highlightedTextCharacter);
		}

		//if we have a match and we are on pseudo code line two (i.e. a new match)
		if(state.matches && (state.lineOfPseudoCode == 2)){			
			//highlight the chars in the string box pattern and string
			//System.out.println("Highlighting pattern forward from " + state.highlightedPatternCharacter + " to " + (this.dummyPattern.length()-state.highlightedPatternCharacter));
			//System.out.println("Highlighting text forward from " + state.highlightedTextCharacter + " to " + (this.dummyText.length()-state.highlightedTextCharacter));
			this.testDisplay.patternBox.highlightChar(state.highlightedPatternCharacter, Color.GREEN);
			this.testDisplay.textBox.highlightChar(state.highlightedTextCharacter, Color.GREEN);

			//highlight the chars in the full string box pattern and string
			this.fullBox.patternBox.highlightChar(state.highlightedPatternCharacter, Color.GREEN);
			this.fullBox.textBox.highlightChar(state.highlightedTextCharacter, Color.GREEN);
		}

		//set all previous characters to red
		//only go up to start of pattern position
		for (int i = 0; i < state.positionOfPattern; i++) {
			if (!state.matches) {
				testDisplay.textBox.highlightChar(i, Color.RED);
				fullBox.textBox.highlightChar(i, Color.RED);
			}
		}
	}

	/**
	 * This method handles the calls when the buttons are pressed or when the slider is
	 * moved.
	 */
	public void actionPerformed(ActionEvent ae) {
		if(ae.getSource() == this.controls.playButton){
			System.out.println("PLAY BUTTON HAS BEEN PRESSED");
			this.playAnimation = true;
			this.controls.backwardButton.setEnabled(false);
			this.controls.forwardButton.setEnabled(false);
			
						
		}
		
		if(ae.getSource() == this.controls.pauseButton){
			System.out.println("PAUSE BUTTON HAS BEEN PRESSED");
			this.playAnimation = false;
			this.controls.backwardButton.setEnabled(true);
			this.controls.forwardButton.setEnabled(true);
		}
		if(ae.getSource() == this.controls.forwardButton){
			
			if(currentStateIndex == animationStates.size()-1){
				//JOptionPane.showMessageDialog(this, "We are at the stsdfgsdfsart of the animation.");
			}
			else this.currentStateIndex++;
			
			if (testAlgorithm instanceof BruteForceTestAlgorithm) {
				displayBruteForceAnimationState(animationStates.get(currentStateIndex));
			}
			else if (testAlgorithm instanceof KMPTestAlgorithm) {
				displayKMPAnimationState(animationStates.get(currentStateIndex));
			}
			else if (testAlgorithm instanceof BoyerMooreTestAlgorithm) {
				displayBoyerMooreAnimationState(animationStates.get(currentStateIndex));
			}
			
		}
		if(ae.getSource() == this.controls.backwardButton){

			if(currentStateIndex == 0){
				JOptionPane.showMessageDialog(this, "We are at the start of the animation.");
			}
			
			else this.currentStateIndex--;
			
			//need to clear highlights in the forward direction
			//for each character from our current position in the text to the end of the text
			for (int i = animationStates.get(currentStateIndex).highlightedTextCharacter;
			i < this.testDisplay.textBox.getStringUsed().length();
			i++){
				this.testDisplay.textBox.highlightChar(i, Color.WHITE);
				this.fullBox.textBox.highlightChar(i, Color.WHITE);
			}
			//need to do this for the pattern as well
			for (int i = animationStates.get(currentStateIndex).highlightedPatternCharacter;
			i < this.testDisplay.patternBox.getStringUsed().length();
			i++){
				this.testDisplay.patternBox.highlightChar(i, Color.WHITE);
				this.fullBox.patternBox.highlightChar(i, Color.WHITE);
			}
			if (testAlgorithm instanceof BruteForceTestAlgorithm) {
				displayBruteForceAnimationState(animationStates.get(currentStateIndex));
			}
			else if (testAlgorithm instanceof KMPTestAlgorithm) {
				displayKMPAnimationState(animationStates.get(currentStateIndex));
			}
			else if (testAlgorithm instanceof BoyerMooreTestAlgorithm) {
				displayBoyerMooreAnimationState(animationStates.get(currentStateIndex));
			}
			//this.currentStateIndex--;
		}
		if(ae.getSource() == this.controls.resetButton){
			System.out.println("RESET BUTTON HAS BEEN PRESSED");
			this.currentStateIndex = 0;
			this.testPseudo.reset();
			
			this.testDisplay.resetPattern();
			this.testDisplay.resetText();
			this.testDisplay.resetString();
			this.testDisplay.clearHighlighting();
			
			this.fullBox.resetPattern();
			this.fullBox.resetString();
			this.fullBox.clearHighlighting();

		}
		
		if(ae.getSource() == this.controls.swapViewsButton){
			this.swapView();
		}
		
	}

	@Override
	public void stateChanged(ChangeEvent e) {
		if (e.getSource() == this.controls.speedSlider){
			int value = (int)	this.controls.speedSlider.getValue();
			System.out.println("SPEED SLIDER HAS CHANGED =" + value);
		}
		
	}

	public boolean isJobDone() {
		return jobDone;
	}

	public void setJobDone(boolean jobDone) {
		this.jobDone = jobDone;
	}
	
	public String getDummyText() {
		return dummyText;
	}

	public String getDummyPattern() {
		return dummyPattern;
	}
}
